/**
 * @author Haidar Osman
 */
var ViewManager = function(stage, name, parent) {
	this.parent = parent;
	this.name = name
	this.views = [];
	this.classes = [];
	this.packages = [];
	this.relations = new RelationObjArray();
	this.currentView = null;
	var that = this;
	this.stage = stage;
	this.consoleStrings = [];
	// this.
	// this.addChat=function(chat)
	// {
	// that.consoleStrings[that.consoleStrings.length] = cmd;
	// if(that.isInFocus()) {
	// that.fillConsole();
	// }
	// }
	this.fillConsole = function() {
		// $("#console").val("");
		// var console = "";
		var i = 0;
		$("#console").empty();
		for( i = that.consoleStrings.length - 1; i >= 0; i--) {
			// console = console + "-" + that.consoleStrings[i] + "\n\n";
			$("#console").append(that.consoleStrings[i]);
		}
		// $("#console").val(console);

	}
	// this.fillConsole();
	this.isInFocus = function() {
		if(that.parent.currentModel) {
			if(that.parent.currentModel.name == that.name) {
				return true;
			}
		}
		return false;
	}
	this.addConsoleString = function(cmd) {
		that.consoleStrings[that.consoleStrings.length] = cmd;
		if(that.isInFocus()) {
			that.fillConsole();
		}
		// if(that.isInFocus()) {
		// $("#chat").prepend("<li><b>" + cmd + "</li></b><br>");
		// }
	}
	this.chatStrings = [];
	this.addChatString = function(cmd) {
		that.chatStrings[that.chatStrings.length] = cmd;
		if(that.isInFocus()) {
			that.fillChat();
		}
	}
	this.fillChat = function() {
		// $("#console").val("");
		// var console = "";
		var i = 0;
		$("#chat").empty();
		for( i = that.chatStrings.length - 1; i >= 0; i--) {
			// console = console + "-" + that.consoleStrings[i] + "\n\n";
			$("#chat").append(that.chatStrings[i]);
		}
		// $("#console").val(console);

	}

	this.clear = function() {
		this.currentView.hide();
	}
	this.addView = function(name, switchToNewView) {
		// if(this.currentView !== null) {
		// this.currentView.hide();
		// }
		// this.currentView = new UMLCanvas(this.stage, name, that, that.relations);
		this.views[this.views.length] = new UMLCanvas(this.stage, name, that, that.relations);
		//this.currentView;
		// this.currentView.show();
		if(switchToNewView) {
			this.switchView(name);
		}
		// else
		// {
		// this.currentView.show();
		// }
		if(that.isInFocus()) {
			addView(name);
		}

	}
	this.addClass = function(x, y, className) {
		if(this.getClass(className) == null) {
			var newClass = new ClassShape(x, y, new Class(className));
			this.classes[this.classes.length] = newClass.classObj;
			newClass.group.visible = true;
			this.currentView.addClass(newClass);
			addItem(newClass.classObj.name);
		} else {
			alert("class already exists");
		}
	}
	this.addClassObj = function(newClass) {
		if(this.getClass(newClass.name) == null) {
			this.classes[this.classes.length] = newClass;
			addItem(newClass.name);
		} else {
			alert("class already exists");
		}
	}
	this.addRelation = function(fromClassObj, toClassObj, type) {
		that.relations.removeRelation(fromClassObj, toClassObj);
		if(type == "uni") {
			var r = new RelationObj(fromClassObj, toClassObj, type);
		} else if(type == "generalization") {
			that.relations.removeRelation(toClassObj, fromClassObj);
			var r = new RelationObj(fromClassObj, toClassObj, type);

		} else {
			var r = new RelationObj(fromClassObj, toClassObj, type);
		}
		that.relations.addRelation(r);

	}
	this.getClass = function(className) {
		var i = 0;
		for( i = 0; i < that.classes.length; i++) {
			if(that.classes[i].name == className) {
				return that.classes[i];
			}
		}
		return null;
	}
	this.removeRelation = function(fromClassObj, toClassObj) {
		that.relations.removeRelation(fromClassObj, toClassObj);
	}

	this.removeClass = function(className) {
		var i = 0;
		for( i = 0; i < that.classes.length; i++) {
			if(that.classes[i].name == className) {
				var j = 0;
				var fromClasses = [];
				var toClasses = [];

				for( j = 0; j < that.relations.members.length; j++) {
					if(that.relations.members[j].fromClass.name == className) {
						fromClasses[fromClasses.length] = that.relations.members[j].fromClass;
						toClasses[toClasses.length] = that.relations.members[j].toClass;
					}
					if(that.relations.members[j].toClass.name == className) {
						fromClasses[fromClasses.length] = that.relations.members[j].fromClass;
						toClasses[toClasses.length] = that.relations.members[j].toClass;
					}
				}
				for( j = 0; j < fromClasses.length; j++) {
					that.relations.removeRelation(fromClasses[j], toClasses[j]);
				}
				for( j = 0; j < that.views.length; j++) {
					that.views[j].removeClass(that.classes[i].name);
				}
				that.classes.splice(i, 1);
				removeItem(className);
				break;
			}
		}
		that.currentView.update();
		that.currentView.updateRelations();
		removeItem(className);
	}

	this.update = function() {
		that.currentView.update();
		that.currentView.updateRelations();
	}
	this.switchView = function(name) {
		var i = 0;
		for( i = 0; i < that.views.length; i++) {
			if(that.views[i].name == name) {
				if(that.currentView) {
					that.currentView.hide();
				}
				that.currentView = that.views[i];
				that.currentView.show();
				that.currentView.update();
				that.currentView.updateRelations();
				that.parent.webSocket.emit("currentView", {
					currentView : name,
					userName : that.parent.userName
				});
				//alert("changes");
				break;
			}
		}
	}
	this.getView = function(name) {
		var i = 0;
		for( i = 0; i < that.views.length; i++) {
			if(that.views[i].name == name) {
				return that.views[i];
				break;
			}
		}
	}
	String.prototype.trim = function() {
		return this.replace(/^\s+|\s+$/g, '');
	};

	this.bindTreeEvents = function() {
		$("#viewTree").dynatree("getRoot").removeChildren();
		$("#classTree").dynatree("getRoot").removeChildren();
		$("#classTree").dynatree();
		$("#viewTree").dynatree();

		$("#classTree").dynatree({
			onClick : function(node, event) {
				// Close menu on click
				if($(".contextMenu:visible").length > 0) {
					$(".contextMenu").hide();
					//          return false;
				}
			},
			onCreate : function(node, span) {
				$(span).contextMenu({
					menu : "myMenu"
				}, function(action, el, pos) {
					// The event was bound to the <span> tag, but the node object
					// is stored in the parent <li> tag
					var node = $.ui.dynatree.getNode(el);
					switch( action ) {
						case "add":
							// that.currentView.addClassObj(that.getClass(node.span.innerText));
							// break;
							var classObjName = node.span.innerText;
							var viewName = that.currentView.name;
							var modelName = that.name;
							var command = {
								name : "addClassObjToView",
								arguments : [modelName, viewName, classObjName]
							}
							that.parent.run(command);
							break;
						case "remove":
							var command = {
								name : "removeClassFromModel",
								arguments : [that.name, node.span.innerText]
							}
							that.parent.run(command);
							// that.parent.removeClassFromModel(that.name,node.span.innerText);
							break;
						default:
							alert("Todo: appply action '" + action + "' to node " + node.span.innerText);
					}
				});
			}
		});
		$("#viewTree").dynatree({
			onActivate : function(node) {
				that.switchView(node.data.title);
				//$("#echoActivated").text(node.data.title + ", key=" + node.data.key);
			}
		});

		var views = that.views;
		for( i = 0; i < views.length; i++) {
			addView(views[i].name);
		}
		var classes = that.classes;
		for( i = 0; i < classes.length; i++) {
			addClass(classes[i].name);
		}
	}
	// this.bindTreeEvents();

	this.getJSON = function() {
		var model = {
			name : that.name,
			classes : [],
			views : [],
			relations : []
		}
		var i = 0;
		for( i = 0; i < that.classes.length; i++) {
			model.classes[i] = that.classes[i].getJSON();
		}
		for( i = 0; i < that.relations.members.length; i++) {
			model.relations[i] = that.relations.members[i].getJSON();
		}
		for( i = 0; i < that.views.length; i++) {
			model.views[i] = that.views[i].getJSON();
		}
		return model;
	}
	this.addNewClassToView = function(viewName, x, y, className) {
		if(this.getClass(className) == null) {
			var newClass = new ClassShape(x, y, new Class(className));
			this.classes[this.classes.length] = newClass.classObj;
			newClass.group.visible = true;
			that.getView(viewName).addClass(newClass);
			if(that.isInFocus()) {
				addItem(newClass.classObj.name);
			}
		} else {
			alert("class already exists");
		}
	}
	this.addCommand = function(command) {
		that.bufferedCommands[that.bufferedCommands.length] = command;
		this.isInReplay = true;
	}
	this.isInReplay = false;
	this.bufferedCommands = [];
	this.lastExecutedCommand = -1;
	this.tempLastExecutedCommand = -1;

	this.bindReplayEvents = function() {
		$('input#next').attr('disabled', false);
		$('input#toLastExecuted').attr('disabled', false);
		$('input#executeAll').attr('disabled', false);
		$("input#next").unbind();
		$("input#executeAll").unbind();
		$("input#next").click(function(event) {
			// console.log(that.tempLastExecutedCommand);
			// console.log(that.tempCommands.length);

			that.tempLastExecutedCommand = that.tempLastExecutedCommand + 1;
			var currentCommand = that.bufferedCommands[that.tempLastExecutedCommand];
			switch(currentCommand.name) {
				case "setRelationToNum" :
				case "setRelationFromNum":
				case "moveClass":
				case  "removeRelation":
				case  "setRelationTitle":
				case  "addRelation":
				case  "addClassObjToView":
				case  "renameAttInClass":
				case  "renameMethodInClass":
				case  "removeAttFromClass":
				case  "removeMethodFromClass":
				case  "addAttToClass":
				case  "addMethodToClass" :
				case "removeClassFromView":
				case  "renameClass" :
				case "addNewClassToView":
					// that.switchModel(currentCommand.arguments[0]);
					that.switchView(currentCommand.arguments[1]);
					setTimeout(function() {
						that.parent.lastExecutedCommand = currentCommand.seqNumber;
						that.parent.execute(currentCommand.name, currentCommand.arguments)
					}, 200);
					break;
				case "addView":
				case "removeClassFromModel":
				case "addModel":
					that.parent.lastExecutedCommand = currentCommand.seqNumber;
					that.parent.execute(currentCommand.name, currentCommand.arguments);
					break;
				default:
					that.parent.lastExecutedCommand= currentCommand.seqNumber;
					that.execute(currentCommand.name, currentCommand.arguments)
					break;
			}
			// that.execute(currentCommand.name, currentCommand.arguments)
			if(that.tempLastExecutedCommand == that.bufferedCommands.length - 1) {
				that.isInReplay = false;
				$('input#next').attr('disabled', true);
				$('input#toLastExecuted').attr('disabled', true);
				$('input#executeAll').attr('disabled', true);
			}
		});

		$("input#executeAll").click(function(event) {
			// that.tempLastExecutedCommand=that.tempLastExecutedCommand+1;
			var i = 0;
			for( i = that.tempLastExecutedCommand + 1; i < that.bufferedCommands.length; i++) {
				// that.parent.execute(that.bufferedCommands[i].name, that.bufferedCommands[i].arguments);
				$("input#next").click();
			}
			that.tempLastExecutedCommand = that.bufferedCommands.length - 1;
			that.isInReplay = false;
			$('input#next').attr('disabled', true);
			$('input#toLastExecuted').attr('disabled', true);
			$('input#executeAll').attr('disabled', true);
		});
		$("input#toLastExecuted").click(function(event) {
			// that.tempLastExecutedCommand=that.tempLastExecutedCommand+1;
			var i = that.tempLastExecutedCommand + 1;
			var serverLastExecuted=that.parent.lastServerCommand;			
			var command=that.bufferedCommands[i]
			while(command.seqNumber<=serverLastExecuted)
			{
				$("input#next").click();
				i++;
				command=that.bufferedCommands[i];
			}			
		});
		
		$("input#chatInput").unbind();
		$("input#chatInput").keydown(function(event) {
			var string = that.parent.userName + ": " + $("input#chatInput").val();
			if(event.which == 13) {
				var command = {
					name : "chat",
					arguments : [that.name, string]
				}
				that.parent.run(command);
				$("input#chatInput").val("");
			}

		});
	}
}